﻿using Microsoft.EntityFrameworkCore;
using Routine.Api.Data;
using Routine.Api.DtoParameters;
using Routine.Api.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Routine.Api.Services
{
    public class CompanyRepository:ICompanyRepository         //里面的代码大部分为异步的。
    {
        private readonly RoutineDbContext _context;
        public CompanyRepository(RoutineDbContext context)
        {
            _context = context 
                ?? throw new ArgumentNullException(nameof(context));//如果没有的话，就返回一个异常。
        }

        public async Task<ICollection<Company>> GetCompaniesAsync(CompanyDtoParameters parameters)
        {
            if (parameters==null)
            {
                throw new ArgumentNullException(nameof(parameters));//如果是空的话返回异常。
            }

            //为了不写翻页，把下边的代码都删掉；

            //if (string.IsNullOrWhiteSpace(parameters.CompanyName)&& //&&和&的区别是是否出现短路,&不会出现短路问题。
            //    string.IsNullOrWhiteSpace(parameters.SearchTerm))
            //{
            //    return await _context.Companies.ToListAsync();
            //}

            var queryExpression = _context.Companies as IQueryable<Company>;//这个可以延迟执行，只有遇到List的时候才开始查询表达式；
            if (!string.IsNullOrWhiteSpace(parameters.CompanyName))//针对查询条件
            {
                parameters.CompanyName = parameters.CompanyName.Trim();
                queryExpression = queryExpression.Where(x => x.Name == parameters.CompanyName);
            }
            if (!string.IsNullOrWhiteSpace(parameters.SearchTerm))//针对搜索条件。
            {
                parameters.SearchTerm = parameters.SearchTerm.Trim();
                queryExpression = queryExpression.Where(x => x.Name.Contains(parameters.SearchTerm) ||
                  x.Introduction.Contains(parameters.SearchTerm));
            }

            //翻页一定要针对数据存储这个级别进行；
            //翻页是在所有的过滤之后写
            queryExpression = queryExpression.
                Skip(parameters.PageSize * (parameters.PageNumber - 1)).Take(parameters.PageSize);//跳过去，然后再查。

            return await queryExpression.ToListAsync();//当遇到TolistAsync的时候，才会真正的查询数据库；
        }

        public async Task<Company> GetCompanyAsync(Guid companyId)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(companyId));
            }

            return await _context.Companies
                .FirstOrDefaultAsync(x => x.Id == companyId);
        }

        public async Task<IEnumerable<Company>>
            GetCompaniesAsync(IEnumerable<Guid> companyIds)
        {
            if (companyIds == null)
            {
                throw new ArgumentNullException(nameof(companyIds));
            }

            return await _context.Companies
                .Where(x => companyIds.Contains(x.Id))
                .OrderBy(x => x.Name)
                .ToListAsync();
        }

        public void AddCompany(Company company)
        {
            if (company == null)
            {
                throw new ArgumentNullException(nameof(company));
            }

            company.Id = Guid.NewGuid();
         
            if (company.Employees != null)
            {
                foreach (var employee in company.Employees)//如果传进来的 company里面有Employees，那么就遍历；
                {
                    employee.Id = Guid.NewGuid();//使用guid方法，添加ID;
                }
            }

            _context.Companies.Add(company);//只是把他添加到了company中，还没有保存到数据库里面；
        }

        public void UpdateCompany(Company company)
        {
            // _context.Entry(company).State = EntityState.Modified;
        }

        public void DeleteCompany(Company company)
        {
            if (company == null)
            {
                throw new ArgumentNullException(nameof(company));
            }

            _context.Companies.Remove(company);
        }

        public async Task<bool> CompanyExistsAsync(Guid companyId)
        {
            if (companyId == Guid.Empty)  //Id为空，这个要用这个检测。
            {
                throw new ArgumentNullException(nameof(companyId));
            }

            return await _context.Companies.AnyAsync(x => x.Id == companyId);
        }
                                              //剩下的部分是针对员工的。
        public async Task<IEnumerable<Employee>> GetEmployeesAsync(Guid companyId,string genderDisplay, string q)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(companyId));
            }
            if (string.IsNullOrWhiteSpace(genderDisplay)&&string.IsNullOrWhiteSpace(q))//如果是空的话
            {
                return await _context.Employees.Where(x => x.CompanyId == companyId) //这是两个等号。
               .OrderBy(x => x.EmployeeNo)
               .ToListAsync();
            }

            var items = _context.Employees.Where(x => x.CompanyId == companyId);//as IQueryable<Employee>; //这个是构建了一个表达式；
            //这句话相当于在组sql语句；

            /*
       as 和is 是如何安全的“向下转型”  ；
1、使用AS运算符进行类型转换
2、先使用IS运算符判断类型是否可以转换，再使用（）运算符进行显示的转换
as如果转换失败，就返回NUll，这样根据是否是null就可以判断是是是否成功，只能是引用类型。

             */

            if (!string.IsNullOrWhiteSpace(genderDisplay))
            {
                genderDisplay = genderDisplay.Trim();   //Trim修剪，去掉空格。 
                var gender = Enum.Parse<Gender>(genderDisplay);//把枚举类型，转化为<T>类型......parse解析，理解

                items = items.Where(x => x.Gender == gender);
            }
            if (!string.IsNullOrWhiteSpace(q))
            {
                q = q.Trim();
                items = items.Where(x => x.EmployeeNo.Contains(q));//Contains 包含；
            }
            return await items.OrderBy(x=>x.EmployeeNo)
                .ToListAsync();
        }

        public async Task<Employee> GetEmployeeAsync(Guid companyId, Guid employeeId)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(companyId));
            }

            if (employeeId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(employeeId));
            }

            return await _context.Employees
                .Where(x => x.CompanyId == companyId && x.Id == employeeId)
                .FirstOrDefaultAsync();
        }

        public void AddEmployee(Guid companyId, Employee employee)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(companyId));
            }

            if (employee == null)
            {
                throw new ArgumentNullException(nameof(employee));
            }

            employee.CompanyId = companyId;
            _context.Employees.Add(employee);
        }

        public void UpdateEmployee(Employee employee)
        {
            // _context.Entry(employee).State = EntityState.Modified;
        }

        public void DeleteEmployee(Employee employee)
        {
            _context.Employees.Remove(employee);
        }

        public async Task<bool> SaveAsync()//这是保存了内容。
        {
            return await _context.SaveChangesAsync() >= 0;//保存写在这里。
        }
    }
}
